package com.learning.spring.security.base.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

import java.util.Optional;

import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasRole;


/**
 * ClassName: AuthorizationConfiguration
 * Description: 授权
 * Date: 2022/7/11 14:18
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class AuthorizationConfiguration {

    @Bean
    SecurityFilterChain web(HttpSecurity http) throws Exception {
        http
                // 指定了多个授权规则。每个规则都按照它们声明的顺序来考虑
                .authorizeHttpRequests(authorize -> authorize
                        // 指定了多个任何用户都可以访问的URL模式。
                        // 说，如果URL以/resources/开头，URL等于/signup或等于/about，任何用户都可以访问请求
                        .mvcMatchers("/resources/**", "/signup", "/about").permitAll()
                        // 任何以/admin/开头的URL将被限制为具有ROLE_ADMIN角色的用户。
                        // 是hasRole方法，所以不需要指定ROLE_前缀
                        .mvcMatchers("/admin/**").hasRole("ADMIN")
                        // 任何以/db/开头的URL都要求用户同时拥有ROLE_ADMIN和ROLE_DBA
                        .mvcMatchers("/db/**").access((authentication, request) ->
                                Optional.of(hasRole("ADMIN").check(authentication, request))
                                        .filter((decision) -> !decision.isGranted())
                                        .orElseGet(() -> hasRole("DBA").check(authentication, request))
                        )
                        // 任何尚未匹配的URL都将被拒绝访问
                        .anyRequest().denyAll()
		);

        return http.build();
    }
}
